
#ifndef P2P_FLOWRATE_FLOWRATE_HPP
#define P2P_FLOWRATE_FLOWRATE_HPP
#include <iostream>
#include <ctime>
#include <stdint.h>
#include <mutex> 
// Percent represents a percentage in increments of 1/1000th of a percent.
typedef int32_t Percent;
typedef int64_t TimeDuration;
typedef int64_t Time;
namespace flowrate
{
// Status represents the current Monitor status. All transfer rates are in bytes
// per second rounded to the nearest byte.
struct Status
{
    bool active;            // Flag indicating an active transfer
    Time start;          // Transfer start time
    TimeDuration duration;       // Time period covered by the statistics
    TimeDuration idle;           // Time since the last transfer of at least 1 byte
    int64_t bytes;          // numbers of bytes transferred
    int64_t samples;        // total number of samples taken
    int64_t instantaneousRate; // Instantaneous transfer rate
    int64_t currentRate;    // Current transfer rate (EMA of InstRate)
    int64_t averageRate;    // Average transfer rate (Bytes / Duration)
    int64_t peakRate;       // Maximum instantaneous transfer rate
    int64_t bytesRemain;    // Number of bytes remaining in the transfer
    TimeDuration timeRemain;     // Estimated time to completion
    Percent progress;       // Overall transfer progress
};
struct Monitor
{
    std::mutex m;
    bool active;    // Flag indicating an active transfer
    TimeDuration start;  // Transfer start time (clock() value)
    int64_t bytes;  // Total number of bytes transferred
    int64_t samples;// Total number of samples taken

    double rSample; // Most recent transfer rate sample (bytes per second)
    double rEMA;    // Exponential moving average of rSample
    double rPeak;   // Peak transfer rate (max of all rSamples)
    double rWindow; // rEMA window (seconds)

    int64_t sBytes; // Number of bytes transferred since sLast
    TimeDuration sLast;  // Most recent sample time (stop time when inactive)
    TimeDuration sRate;  // Sampling rate

    int64_t tBytes; // Number of bytes expected in the current transfer
    TimeDuration tLast;  // Time of the most recent transfer of at least 1 byte


    Monitor(int64_t sampleRate, int64_t windowSize);

    // Update records the transfer of n bytes and returns n. It should be called
    // after each Read/Write operation, even if n is 0.
    int64_t update(int n);  // return the clock()

    int64_t Update(int n);  // add the lock surround update and return n

    // Hack to set the current rEMA.
    void setREMA(double frEMA);

    // Done marks the transfer as finished and prevents any further updates or
    // limiting. Instantaneous and current transfer rates drop to 0. Update, IO, and
    // Limit methods become NOOPs. It returns the total number of bytes transferred.
    int64_t done();

    // reset clears the current sample state in preparation for the next sample.
    void reset(int64_t sampleTime);

    Status status();

    // SetTransferSize specifies the total size of the data transfer, which allows
    // the Monitor to calculate the overall progress and time to completion.
    void setTransferSize(int64_t size);

    // waitNextSample sleeps for the remainder of the current sample. The lock is
    // released and reacquired during the actual sleep period, so it's possible for
    // the transfer to be inactive when this method returns.
    TimeDuration waitNextSample(TimeDuration now);
};




}
#endif // !P2P_FLOWRATE_FLOWRATE_HPP